package org.tamal.servlet;

import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.tamal.SessionKey;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

/**
 * LoginServlet is used to log-in through Open Authentication v2.
 * @author Tamal Kanti Nath
 */
public final class LoginServlet extends HttpServlet {

    private static final long serialVersionUID = 5099443306374469482L;

    private final transient Logger log = Logger.getLogger(getClass().getName());

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        log.info("Query String: " + request.getQueryString());
        UserService userService = UserServiceFactory.getUserService();
        if (request.getParameter("logout") != null) {
            request.getSession().invalidate();
            if (request.getUserPrincipal() == null) {
                response.sendRedirect("/");
            } else {
                response.sendRedirect(userService.createLogoutURL("/"));
            }
            return;
        }
        Entity user = null;
		if (userService.isUserLoggedIn()) {
			user = fetchOpenIdUser(userService.getCurrentUser());
		}
        saveUser(user);
        request.getSession().setAttribute(SessionKey.USER.name(), user);
        String redirect = (String) request.getSession().getAttribute(
                SessionKey.REDIRECT.name());
        if (redirect == null) {
            response.sendRedirect("/");
        } else {
            request.getSession().removeAttribute(SessionKey.REDIRECT.name());
            response.sendRedirect(redirect);
        }
    }

	private void saveUser(Entity user) {
        Date now = new Date();
        user.setProperty("firstLogin", now);
        user.setProperty("lastLogin", now);
        user.setProperty("loginCount", 1L);
        DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
        try {
            Entity entity = ds.get(user.getKey());
            Date firstLogin = (Date) entity.getProperty("firstLogin");
            user.setProperty("firstLogin", firstLogin);
            Long loginCount = (Long) entity.getProperty("loginCount");
            user.setProperty("loginCount", loginCount + 1);
        } catch (EntityNotFoundException e) {
            log.throwing(getClass().getName(), "saveUser", e);
        }
        ds.put(user);
    }

    private static Entity fetchOpenIdUser(User user) {
        Entity entity = new Entity("user", user.getUserId());
        entity.setProperty("name", user.getNickname());
        entity.setProperty("email", user.getEmail());
        entity.setProperty("domain", user.getAuthDomain());
        entity.setProperty("federatedId", user.getFederatedIdentity());
        return entity;
    }
}
